<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8'>

    <link rel="stylesheet" type="text/css" 
      href="/assets/css/straybirds.css" media="screen" />
    <link rel="stylesheet" type="text/css" 
      href="/assets/css/pygments.css" media="screen" />

    <!-- MathJax Section Start -->

    <script type="text/javascript"
    src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
    </script>
    <script>
        MathJax.Hub.Config({
              tex2jax: {
              skipTags: ['script', 'noscript', 'style', 'textarea', 'pre']
              }
        });
        MathJax.Hub.Queue(function() {
            var all = MathJax.Hub.getAllJax(), i;
            for(i=0; i < all.length; i += 1) {
                all[i].SourceElement().parentNode.className += ' has-jax';
            }
        });
    </script>

    <!-- MathJax Section End -->

    <!-- Google Analytics Start-->
    <script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

  ga('create', 'UA-48100787-1', 'minixalpha.github.io');
  ga('send', 'pageview');

</script>

    <!-- Google Analytics End -->

    <title>首页</title>
  </head>

  <body>
    <div class="container">
      <header>
        <div class="container">
          <h1>
              <a href="/" title="Home Page"> 潇湘夜雨 </a>
          <span class="github-src">
            <a href ="https://github.com/minixalpha/minixalpha.github.io"
               target="_blank"
               title="Fork me on GitHub">
              <img src="/assets/images/GitHub-Mark-Light-32px.png" alt="">
            </a>
          </span>
          </h1>
        </div>
      </header>

      <aside id="left-side">
        <h2> 分类 </h2>
  <ul class="category-list">
      
            
                <li>
                <a href="/categories/计算机系统"> 计算机系统 (3) </a>
                </li>
            
      
            
                <li>
                <a href="/categories/java"> java (1) </a>
                </li>
            
      
            
                <li>
                <a href="/categories/技术"> 技术 (5) </a>
                </li>
            
      
            
                <li>
                <a href="/categories/工具"> 工具 (4) </a>
                </li>
            
      
            
                <li>
                <a href="/categories/科研"> 科研 (5) </a>
                </li>
            
      
            
                <li>
                <a href="/categories/生活"> 生活 (1) </a>
                </li>
            
      
            
                <li>
                <a href="/categories/思想"> 思想 (2) </a>
                </li>
            
      
            
                <li>
                <a href="/categories/c语言"> c语言 (4) </a>
                </li>
            
      
            
                <li>
                <a href="/categories/虚拟机"> 虚拟机 (1) </a>
                </li>
            
      
            
                <li>
                <a href="/categories/英语"> 英语 (8) </a>
                </li>
            
      
            
                <li>
                <a href="/categories/读书"> 读书 (1) </a>
                </li>
            
      
            
                <li>
                <a href="/categories/源代码阅读"> 源代码阅读 (10) </a>
                </li>
            
      
  </ul>

      </aside>

      <aside id="right-side">
        <h2> 归档 </h2>
  <ul class="archive-list">
    
    
    
        
        
        
        
            
            <li>
                <a href="/2014/05">
                    2014-05 (1)
                </a>
            </li>

        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
            
            <li>
                <a href="/2014/04">
                    2014-04 (3)
                </a>
            </li>

        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
            
            <li>
                <a href="/2014/03">
                    2014-03 (11)
                </a>
            </li>

        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
            
            <li>
                <a href="/2014/02">
                    2014-02 (6)
                </a>
            </li>

        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
            
            <li>
                <a href="/2014/01">
                    2014-01 (3)
                </a>
            </li>

        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
            
            <li>
                <a href="/2013/11">
                    2013-11 (10)
                </a>
            </li>

        
        
    
        
        
        
        
    
        
        
        
        
    
        
        
        
        
            
            <li>
                <a href="/2013/10">
                    2013-10 (3)
                </a>
            </li>

        
        
    
  </ul>

      </aside>

      <article>

<ul class="post-list">
    
    <li>
      <div class="post-title">
        <a href="/%E6%BA%90%E4%BB%A3%E7%A0%81%E9%98%85%E8%AF%BB/2013/11/18/blog_arch.html"> web.py 项目架构分析之 blog</a> </br>
      </div>

      <div class="post-info">
        <ol>
          <li class="post-time">2013-11-18</li> 
          <li class="post-category"> 
           源代码阅读
          </li>
        </ol>
      </div>

      <div class="post-preview">
        <h1>web.py 项目之 blog</h1>

<h2>目录树</h2>
<div class="highlight"><pre><code class="text language-text" data-lang="text">src/
├── blog.py
├── model.py
├── schema.sql
└── templates
    ├── base.html
    ├── edit.html
    ├── index.html
    ├── new.html
    └── view.html

1 directory, 8 files
</code></pre></div>
<h2>项目说明</h2>

<p>项目来自 <a href="http://webpy.org/src/blog/0.3">webpy.org</a>,
主要实现一个基于web的博客系统，实现了基本的增删查改。</p>

<h2>结构分析</h2>

<h3>控制模块</h3>

<p>控制模块包括 blog.py</p>
<div class="highlight"><pre><code class="python language-python" data-lang="python"><span class="sd">&quot;&quot;&quot; Basic blog using webpy 0.3 &quot;&quot;&quot;</span>
<span class="kn">import</span> <span class="nn">web</span>
<span class="kn">import</span> <span class="nn">model</span>

<span class="c">### Url mappings</span>

<span class="n">urls</span> <span class="o">=</span> <span class="p">(</span>
    <span class="s">&#39;/&#39;</span><span class="p">,</span> <span class="s">&#39;Index&#39;</span><span class="p">,</span>
    <span class="s">&#39;/view/(\d+)&#39;</span><span class="p">,</span> <span class="s">&#39;View&#39;</span><span class="p">,</span>
    <span class="s">&#39;/new&#39;</span><span class="p">,</span> <span class="s">&#39;New&#39;</span><span class="p">,</span>
    <span class="s">&#39;/delete/(\d+)&#39;</span><span class="p">,</span> <span class="s">&#39;Delete&#39;</span><span class="p">,</span>
    <span class="s">&#39;/edit/(\d+)&#39;</span><span class="p">,</span> <span class="s">&#39;Edit&#39;</span><span class="p">,</span>
<span class="p">)</span>
</code></pre></div> 
        <a href="/%E6%BA%90%E4%BB%A3%E7%A0%81%E9%98%85%E8%AF%BB/2013/11/18/blog_arch.html"> Read More ... </a> </br>
      </div>

    </li>
    
    <li>
      <div class="post-title">
        <a href="/%E6%BA%90%E4%BB%A3%E7%A0%81%E9%98%85%E8%AF%BB/2013/11/17/todolist_arch.html"> web.py 项目架构分析之 todolist</a> </br>
      </div>

      <div class="post-info">
        <ol>
          <li class="post-time">2013-11-17</li> 
          <li class="post-category"> 
           源代码阅读
          </li>
        </ol>
      </div>

      <div class="post-preview">
        <h1>web.py 项目之 todolist</h1>

<h2>目录树</h2>
<div class="highlight"><pre><code class="text language-text" data-lang="text">.
└── src
    ├── model.py
    ├── schema.sql
    ├── templates
    │   ├── base.html
    │   └── index.html
    ├── todo.py

2 directories, 8 files
</code></pre></div>
<h2>项目说明</h2>

<p>项目来自 <a href="http://webpy.org/src/todo-list/0.3">webpy.org</a>,
主要实现一个基于web的 todolist，就是可以添加删除一些任务。
非常简单</p>

<h2>结构分析</h2>

<h3>控制模块</h3>

<p>控制模块只有todo.py</p>
<div class="highlight"><pre><code class="python language-python" data-lang="python"><span class="sd">&quot;&quot;&quot; Basic todo list using webpy 0.3 &quot;&quot;&quot;</span>
<span class="kn">import</span> <span class="nn">web</span>
<span class="kn">import</span> <span class="nn">model</span>

<span class="c">### Url mappings</span>

<span class="n">urls</span> <span class="o">=</span> <span class="p">(</span>
    <span class="s">&#39;/&#39;</span><span class="p">,</span> <span class="s">&#39;Index&#39;</span><span class="p">,</span>
    <span class="s">&#39;/del/(\d+)&#39;</span><span class="p">,</span> <span class="s">&#39;Delete&#39;</span>
<span class="p">)</span>
</code></pre></div> 
        <a href="/%E6%BA%90%E4%BB%A3%E7%A0%81%E9%98%85%E8%AF%BB/2013/11/17/todolist_arch.html"> Read More ... </a> </br>
      </div>

    </li>
    
    <li>
      <div class="post-title">
        <a href="/%E6%BA%90%E4%BB%A3%E7%A0%81%E9%98%85%E8%AF%BB/2013/11/14/skeleton_arch.html"> web.py 项目架构分析之 skeleton</a> </br>
      </div>

      <div class="post-info">
        <ol>
          <li class="post-time">2013-11-14</li> 
          <li class="post-category"> 
           源代码阅读
          </li>
        </ol>
      </div>

      <div class="post-preview">
        <h1>web.py 项目之 skeleton</h1>

<p>skeleton 是 web.py 官网上给出的一个最简单的项目结构示例。</p>

<h2>目录树</h2>
<div class="highlight"><pre><code class="text language-text" data-lang="text">.
└── src  
    ├── code.py  
    ├── config.py  
    ├── db.py  
    ├── sql
    │   └── tables.sql
    ├── templates
    │   ├── base.html
    │   ├── item.html
    │   └── listing.html
    └── view.py

3 directories, 9 files
</code></pre></div>
<h2>结构分析</h2>

<h3>控制模块</h3>
<div class="highlight"><pre><code class="python language-python" data-lang="python"><span class="c">#code.py</span>

<span class="kn">import</span> <span class="nn">web</span>
<span class="kn">import</span> <span class="nn">view</span><span class="o">,</span> <span class="nn">config</span>
<span class="kn">from</span> <span class="nn">view</span> <span class="kn">import</span> <span class="n">render</span>

<span class="n">urls</span> <span class="o">=</span> <span class="p">(</span>
    <span class="s">&#39;/&#39;</span><span class="p">,</span> <span class="s">&#39;index&#39;</span>
<span class="p">)</span>

<span class="k">class</span> <span class="nc">index</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">GET</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">render</span><span class="o">.</span><span class="n">base</span><span class="p">(</span><span class="n">view</span><span class="o">.</span><span class="n">listing</span><span class="p">())</span>

<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&quot;__main__&quot;</span><span class="p">:</span>
    <span class="n">app</span> <span class="o">=</span> <span class="n">web</span><span class="o">.</span><span class="n">application</span><span class="p">(</span><span class="n">urls</span><span class="p">,</span> <span class="nb">globals</span><span class="p">())</span>
    <span class="n">app</span><span class="o">.</span><span class="n">internalerror</span> <span class="o">=</span> <span class="n">web</span><span class="o">.</span><span class="n">debugerror</span>
    <span class="n">app</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</code></pre></div>
<p><code>code</code> 模块作为入口:</p>

<ul>
<li>app 的创建与启动</li>
<li>url　与　处理类的映射与处理入口</li>
</ul>

<p>但是，具体的处理并不在这里实现。而是放在了 <code>view</code> 模块中。</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">这一模块是MVC中的C吗？
</code></pre></div>
<h3>显示模块</h3>
<div class="highlight"><pre><code class="python language-python" data-lang="python"><span class="c">#view.py</span>

<span class="kn">import</span> <span class="nn">web</span>
<span class="kn">import</span> <span class="nn">db</span>
<span class="kn">import</span> <span class="nn">config</span>

<span class="n">t_globals</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span>
  <span class="n">datestr</span><span class="o">=</span><span class="n">web</span><span class="o">.</span><span class="n">datestr</span><span class="p">,</span>
<span class="p">)</span>
<span class="n">render</span> <span class="o">=</span> <span class="n">web</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="s">&#39;templates/&#39;</span><span class="p">,</span> <span class="n">cache</span><span class="o">=</span><span class="n">config</span><span class="o">.</span><span class="n">cache</span><span class="p">,</span> 
    <span class="nb">globals</span><span class="o">=</span><span class="n">t_globals</span><span class="p">)</span>
<span class="n">render</span><span class="o">.</span><span class="n">_keywords</span><span class="p">[</span><span class="s">&#39;globals&#39;</span><span class="p">][</span><span class="s">&#39;render&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">render</span>

<span class="k">def</span> <span class="nf">listing</span><span class="p">(</span>\<span class="o">**</span><span class="n">k</span><span class="p">):</span>
    <span class="n">l</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">listing</span><span class="p">(</span>\<span class="o">**</span><span class="n">k</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">render</span><span class="o">.</span><span class="n">listing</span><span class="p">(</span><span class="n">l</span><span class="p">)</span>
</code></pre></div>
<p>从这里可以看出　<code>view</code> 模块</p>

<ul>
<li>与模板关联 </li>
<li>从数据库中取数据，然后发给模板</li>
</ul>

<p>我们再来看看模板:</p>
<div class="highlight"><pre><code class="html language-html" data-lang="html"><span class="c">&lt;!--</span>
<span class="c">    templates/base.html</span>
<span class="c">--&gt;</span>

$def with (page, title=None)
<span class="nt">&lt;html&gt;&lt;head&gt;</span>
<span class="nt">&lt;title&gt;</span>my site\
$if title: : $title\
<span class="nt">&lt;/title&gt;</span>
<span class="nt">&lt;/head&gt;&lt;body&gt;</span>
<span class="nt">&lt;h1&gt;&lt;a</span> <span class="na">href=</span><span class="s">&quot;/&quot;</span><span class="nt">&gt;</span>my site<span class="nt">&lt;/a&gt;&lt;/h1&gt;</span>
$:page   
<span class="nt">&lt;/body&gt;&lt;/html&gt;</span>
</code></pre></div>
<p><code>base.html</code> 是所有模块的公共部分，每个模块只需要提供
它的 <code>page</code> ，即内容就可以了。</p>
<div class="highlight"><pre><code class="html language-html" data-lang="html"><span class="c">&lt;!--</span>
<span class="c">    templates/listing.html</span>
<span class="c">--&gt;</span>

$def with (items)

$for item in items:
    $:render.item(item)
</code></pre></div><div class="highlight"><pre><code class="text language-text" data-lang="text">这一模块是MVC中的V吗
</code></pre></div>
<h3>数据操作</h3>

<p>数据库操作分三部分</p>

<ul>
<li>sql/tables.sql 数据库表定义</li>
<li>config.py 数据库连接</li>
<li>db.py 数据库操作</li>
</ul>
<div class="highlight"><pre><code class="text language-text" data-lang="text">/* tables.sql */
CREATE TABLE items (
    id serial primary key,
    author_id int references users,
    body text,
    created timestamp default current_timestamp 
);
</code></pre></div><div class="highlight"><pre><code class="text language-text" data-lang="text">#config.py

import web
DB = web.database(dbn=&#39;mysql&#39;, db=&#39;skeleton&#39;, user=&#39;root&#39;, pw=&#39;xx&#39;)
cache = False
</code></pre></div><div class="highlight"><pre><code class="text language-text" data-lang="text"># db.py
import config

def listing(\**k):
    return config.DB.select(&#39;items&#39;, **k)
</code></pre></div><div class="highlight"><pre><code class="text language-text" data-lang="text">这是MVC中的M吗
</code></pre></div>
<p>这是 web.py 中最基本的一个项目结构。应该是使用的MVC设计模式。但是
因为程序本身不大，还体会不到 MVC 的好处。</p>
 
        <a href="/%E6%BA%90%E4%BB%A3%E7%A0%81%E9%98%85%E8%AF%BB/2013/11/14/skeleton_arch.html"> Read More ... </a> </br>
      </div>

    </li>
    
    <li>
      <div class="post-title">
        <a href="/%E6%BA%90%E4%BB%A3%E7%A0%81%E9%98%85%E8%AF%BB/2013/11/14/Application_testreloader.html"> web.py 源代码分析之　web.test.application.test_reloader</a> </br>
      </div>

      <div class="post-info">
        <ol>
          <li class="post-time">2013-11-14</li> 
          <li class="post-category"> 
           源代码阅读
          </li>
        </ol>
      </div>

      <div class="post-preview">
        <h1>分模块测试</h1>

<h2>application.py</h2>

<p>对 application.py 的测试，调用命令：</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">python test/application.py
</code></pre></div>
<h3>test_reloader(self)</h3>
<div class="highlight"><pre><code class="python language-python" data-lang="python"><span class="k">def</span> <span class="nf">test_reloader</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="n">write</span><span class="p">(</span><span class="s">&#39;foo.py&#39;</span><span class="p">,</span> <span class="n">data</span> <span class="o">%</span> <span class="nb">dict</span><span class="p">(</span><span class="n">classname</span><span class="o">=</span><span class="s">&#39;a&#39;</span><span class="p">,</span> <span class="n">output</span><span class="o">=</span><span class="s">&#39;a&#39;</span><span class="p">))</span>
    <span class="kn">import</span> <span class="nn">foo</span>
    <span class="n">app</span> <span class="o">=</span> <span class="n">foo</span><span class="o">.</span><span class="n">app</span>

    <span class="bp">self</span><span class="o">.</span><span class="n">assertEquals</span><span class="p">(</span><span class="n">app</span><span class="o">.</span><span class="n">request</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">data</span><span class="p">,</span> <span class="s">&#39;a&#39;</span><span class="p">)</span>

    <span class="c"># test class change</span>
    <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
    <span class="n">write</span><span class="p">(</span><span class="s">&#39;foo.py&#39;</span><span class="p">,</span> <span class="n">data</span> <span class="o">%</span> <span class="nb">dict</span><span class="p">(</span><span class="n">classname</span><span class="o">=</span><span class="s">&#39;a&#39;</span><span class="p">,</span> <span class="n">output</span><span class="o">=</span><span class="s">&#39;b&#39;</span><span class="p">))</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">assertEquals</span><span class="p">(</span><span class="n">app</span><span class="o">.</span><span class="n">request</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">data</span><span class="p">,</span> <span class="s">&#39;b&#39;</span><span class="p">)</span>

    <span class="c"># test urls change</span>
    <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
    <span class="n">write</span><span class="p">(</span><span class="s">&#39;foo.py&#39;</span><span class="p">,</span> <span class="n">data</span> <span class="o">%</span> <span class="nb">dict</span><span class="p">(</span><span class="n">classname</span><span class="o">=</span><span class="s">&#39;c&#39;</span><span class="p">,</span> <span class="n">output</span><span class="o">=</span><span class="s">&#39;c&#39;</span><span class="p">))</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">assertEquals</span><span class="p">(</span><span class="n">app</span><span class="o">.</span><span class="n">request</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">data</span><span class="p">,</span> <span class="s">&#39;c&#39;</span><span class="p">)</span>
</code></pre></div>
<p>总的来说，这个过程会生成一个 foo.py 文件</p>
<div class="highlight"><pre><code class="python language-python" data-lang="python"><span class="kn">import</span> <span class="nn">web</span>

<span class="n">urls</span> <span class="o">=</span> <span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">,</span> <span class="s">&quot;a&quot;</span><span class="p">)</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">web</span><span class="o">.</span><span class="n">application</span><span class="p">(</span><span class="n">urls</span><span class="p">,</span> <span class="nb">globals</span><span class="p">(),</span> <span class="n">autoreload</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">a</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">GET</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s">&quot;a&quot;</span>
</code></pre></div>
<p>这是一个典型的 web 服务端应用程序，表示对 <code>/</code> 发起 <code>GET</code>
请求时，会调用 <code>class a</code> 中的 <code>GET</code> 函数，测试就是看看
web.application 是否可以正常完成任务，即是否可以正确返回&quot;a&quot;</p>

<p>下面详细看代码。</p>

<p>首先使用 <code>write</code> 生成了一个 <code>foo.py</code> 程序:</p>
<div class="highlight"><pre><code class="python language-python" data-lang="python">        <span class="n">write</span><span class="p">(</span><span class="s">&#39;foo.py&#39;</span><span class="p">,</span> <span class="n">data</span> <span class="o">%</span> <span class="nb">dict</span><span class="p">(</span><span class="n">classname</span><span class="o">=</span><span class="s">&#39;a&#39;</span><span class="p">,</span> <span class="n">output</span><span class="o">=</span><span class="s">&#39;a&#39;</span><span class="p">))</span>
</code></pre></div>
<p>write 源代码:</p>
<div class="highlight"><pre><code class="python language-python" data-lang="python"><span class="k">def</span> <span class="nf">write</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="n">data</span><span class="p">):</span>
    <span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="s">&#39;w&#39;</span><span class="p">)</span>
    <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
    <span class="n">f</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</code></pre></div>
<p>data 定义:
```python
data = &quot;&quot;&quot;
import web</p>

<p>urls = (&quot;/&quot;, &quot;%(classname)s&quot;)
app = web.application(urls, globals(), autoreload=True)</p>

<p>class %(classname)s:
    def GET(self):
        return &quot;%(output)s&quot;</p>

<p>&quot;&quot;&quot;
```</p>

<p><code>data</code> 相当于一个小型 web 程序的模板，类名和返回值由
一个 <code>dict</code> 指定，生成一个字符串，由 <code>write</code> 生成文件。 </p>

<p>下面是类别和返回值为 <code>a</code> 时的 <code>foo.py</code></p>
<div class="highlight"><pre><code class="python language-python" data-lang="python"><span class="kn">import</span> <span class="nn">web</span>

<span class="n">urls</span> <span class="o">=</span> <span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">,</span> <span class="s">&quot;a&quot;</span><span class="p">)</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">web</span><span class="o">.</span><span class="n">application</span><span class="p">(</span><span class="n">urls</span><span class="p">,</span> <span class="nb">globals</span><span class="p">(),</span> <span class="n">autoreload</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">a</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">GET</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s">&quot;a&quot;</span>
</code></pre></div>
<p>测试的方式采用 <code>TestCase</code> 中的 <code>assertEquals</code> 函数，比较
实际值与预测值。</p>
<div class="highlight"><pre><code class="python language-python" data-lang="python"><span class="kn">import</span> <span class="nn">foo</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">foo</span><span class="o">.</span><span class="n">app</span>
<span class="bp">self</span><span class="o">.</span><span class="n">assertEquals</span><span class="p">(</span><span class="n">app</span><span class="o">.</span><span class="n">request</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">data</span><span class="p">,</span> <span class="s">&#39;a&#39;</span><span class="p">)</span>
</code></pre></div>
<p><code>app.request(&#39;/&#39;)</code> 会得到一个Storage类型的值：</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">&lt;Storage {&#39;status&#39;: &#39;200 OK&#39;, &#39;headers&#39;: {}, &#39;header_items&#39;: [], &#39;data&#39;: &#39;a&#39;}&gt;
</code></pre></div>
<p>其中的 <code>data</code> 就是 <code>foo.py</code> 中 <code>GET</code> 返回的值。 </p>

<p>我对这个 <code>app.request(&#39;/&#39;)</code> 是比较困惑的。以 <code>foo.py</code> 为例，
之前写程序时，一般是有一个这样的程序：</p>
<div class="highlight"><pre><code class="python language-python" data-lang="python"><span class="kn">import</span> <span class="nn">web</span>

<span class="n">urls</span> <span class="o">=</span> <span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">,</span> <span class="s">&quot;a&quot;</span><span class="p">)</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">web</span><span class="o">.</span><span class="n">application</span><span class="p">(</span><span class="n">urls</span><span class="p">,</span> <span class="nb">globals</span><span class="p">(),</span> <span class="n">autoreload</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">a</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">GET</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s">&quot;a&quot;</span>

<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&quot;__main__&quot;</span><span class="p">:</span>
    <span class="n">app</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</code></pre></div>
<p>然后在浏览器中请求 <code>0.0.0.0:8080/</code> 。
而在 <code>request</code> 之前，也没看到 <code>run</code> 啊，怎么就能 <code>request</code> 回
数据呢，而且通过上述代码运行后，程序会一直运行直到手动关闭，
而 <code>request</code> 的方式则是测试完后，整个程序也结束了。</p>

<p>所以，下一部，想比较一下 <code>application.run</code> 和 <code>application.request</code> 的不同。</p>

<p>我们只看关键部分，即返回的值是如何被设值的。</p>

<p>在 <code>web.application.request</code> 中:</p>
<div class="highlight"><pre><code class="python language-python" data-lang="python"><span class="k">def</span> <span class="nf">request</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">localpart</span><span class="o">=</span><span class="s">&#39;/&#39;</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="s">&#39;GET&#39;</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span>
            <span class="n">host</span><span class="o">=</span><span class="s">&quot;0.0.0.0:8080&quot;</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">https</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">):</span>

    <span class="o">...</span>

<span class="n">response</span> <span class="o">=</span> <span class="n">web</span><span class="o">.</span><span class="n">storage</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">start_response</span><span class="p">(</span><span class="n">status</span><span class="p">,</span> <span class="n">headers</span><span class="p">):</span>
    <span class="n">response</span><span class="o">.</span><span class="n">status</span> <span class="o">=</span> <span class="n">status</span>
    <span class="n">response</span><span class="o">.</span><span class="n">headers</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">headers</span><span class="p">)</span>
    <span class="n">response</span><span class="o">.</span><span class="n">header_items</span> <span class="o">=</span> <span class="n">headers</span>
<span class="n">response</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="s">&quot;&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">wsgifunc</span><span class="p">()(</span><span class="n">env</span><span class="p">,</span> <span class="n">start_response</span><span class="p">))</span>
<span class="k">return</span> <span class="n">response</span>
</code></pre></div>
<p>上述代码中 <code>self.wsgifunc()(env, start_response)</code> 比较另人困惑，
我还以为是调用函数的新方式呢，然后看了一下 <code>wsgifunc</code> 的代码，
它会返回一个函数<code>wsgi</code>，<code>wsgi</code>以 <code>(env, start_response)</code> 为参数。
在 <code>wsgi</code> 内部，又会调用 <code>handle_with_processors</code>, <code>handle_with_processors</code> 会再调用 <code>handle</code></p>
<div class="highlight"><pre><code class="python language-python" data-lang="python">    <span class="k">def</span> <span class="nf">handle</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">fn</span><span class="p">,</span> <span class="n">args</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_match</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">mapping</span><span class="p">,</span> <span class="n">web</span><span class="o">.</span><span class="n">ctx</span><span class="o">.</span><span class="n">path</span><span class="p">)</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_delegate</span><span class="p">(</span><span class="n">fn</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">fvars</span><span class="p">,</span> <span class="n">args</span><span class="p">)</span>
</code></pre></div>
<p>测试了一下，<code>self._match()</code> 会得到类名, <code>self._delegate</code> 会
得到返回的字符串，即 <code>GET</code>的返回值。</p>

<p>进入 <code>self._delegate</code>, 会最终调用一个关键函数 <code>handle_class</code>:</p>
<div class="highlight"><pre><code class="python language-python" data-lang="python"><span class="k">def</span> <span class="nf">handle_class</span><span class="p">(</span><span class="n">cls</span><span class="p">):</span>
    <span class="n">meth</span> <span class="o">=</span> <span class="n">web</span><span class="o">.</span><span class="n">ctx</span><span class="o">.</span><span class="n">method</span>
    <span class="k">if</span> <span class="n">meth</span> <span class="o">==</span> <span class="s">&#39;HEAD&#39;</span> <span class="ow">and</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">cls</span><span class="p">,</span> <span class="n">meth</span><span class="p">):</span>
        <span class="n">meth</span> <span class="o">=</span> <span class="s">&#39;GET&#39;</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">cls</span><span class="p">,</span> <span class="n">meth</span><span class="p">):</span>
        <span class="k">raise</span> <span class="n">web</span><span class="o">.</span><span class="n">nomethod</span><span class="p">(</span><span class="n">cls</span><span class="p">)</span>
    <span class="n">tocall</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">cls</span><span class="p">(),</span> <span class="n">meth</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">tocall</span><span class="p">(</span>\<span class="o">*</span><span class="n">args</span><span class="p">)</span>
</code></pre></div>
<p>参数<code>cls</code>值为<code>foo.a</code>, <code>meth</code> 会得到方法名 <code>GET</code>, 然后
<code>tocall</code> 会得到函数 <code>a.GET</code>, 至此，我们终于得以调用，
<code>GET</code>函数，得到了返回的字符串。</p>

<p>从整个过程可以看出，没有启动服务器的代码，只是不断地调用
函数，最终来到 <code>GET</code> 函数。</p>
 
        <a href="/%E6%BA%90%E4%BB%A3%E7%A0%81%E9%98%85%E8%AF%BB/2013/11/14/Application_testreloader.html"> Read More ... </a> </br>
      </div>

    </li>
    
    <li>
      <div class="post-title">
        <a href="/%E6%BA%90%E4%BB%A3%E7%A0%81%E9%98%85%E8%AF%BB/2013/11/14/Application_testUppercaseMethods.html"> web.py 源代码分析之 web.test.application.test_UppercaseMethods</a> </br>
      </div>

      <div class="post-info">
        <ol>
          <li class="post-time">2013-11-14</li> 
          <li class="post-category"> 
           源代码阅读
          </li>
        </ol>
      </div>

      <div class="post-preview">
        <h1>分模块测试</h1>

<h2>application.py</h2>

<p>对 application.py 的测试，调用命令：</p>
<div class="highlight"><pre><code class="text language-text" data-lang="text">python test/application.py
</code></pre></div> 
        <a href="/%E6%BA%90%E4%BB%A3%E7%A0%81%E9%98%85%E8%AF%BB/2013/11/14/Application_testUppercaseMethods.html"> Read More ... </a> </br>
      </div>

    </li>
    
</ul>

<!-- Pagination links -->

<div class="pagination">
  
    <a href="/page5">&laquo; Prev</a>
  

  
    
      <a href="/index.html">1</a>
    
  
    
      <a href="/page2">2</a>
    
  
    
      <a href="/page3">3</a>
    
  
    
      <a href="/page4">4</a>
    
  
    
      <a href="/page5">5</a>
    
  
    
      6
    
  
    
      <a href="/page7">7</a>
    
  
    
      <a href="/page8">8</a>
    
  

  
    <a href="/page7">Next &raquo;</a>
  
</div>



      </article>

      <div class="comments">
        
      </div>


      <footer>
        Copyright (c) minixalpha 2014
      </footer>

    </div>
  </body>
</html>
